#ifndef THINK_THINK_FILE_H
#define THINK_THINK_FILE_H

static char* think_file =
	"\n"
	"// +----------------------------------------------------------------------\n"
	"// | ThinkPHP [ WE CAN DO IT JUST THINK ]\n"
	"// +----------------------------------------------------------------------\n"
	"// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.\n"
	"// +----------------------------------------------------------------------\n"
	"// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )\n"
	"// +----------------------------------------------------------------------\n"
	"// | Author: liu21st <liu21st@gmail.com>\n"
	"// +----------------------------------------------------------------------\n"
	"\n"
	"namespace think;\n"
	"\n"
	"use SplFileObject;\n"
	"\n"
	"class File extends SplFileObject\n"
	"{\n"
	"    /**\n"
	"     * @var string 错误信息\n"
	"     */\n"
	"    private $error = \'\';\n"
	"\n"
	"    /**\n"
	"     * @var string 当前完整文件名\n"
	"     */\n"
	"    protected $filename;\n"
	"\n"
	"    /**\n"
	"     * @var string 上传文件名\n"
	"     */\n"
	"    protected $saveName;\n"
	"\n"
	"    /**\n"
	"     * @var string 文件上传命名规则\n"
	"     */\n"
	"    protected $rule = \'date\';\n"
	"\n"
	"    /**\n"
	"     * @var array 文件上传验证规则\n"
	"     */\n"
	"    protected $validate = [];\n"
	"\n"
	"    /**\n"
	"     * @var bool 单元测试\n"
	"     */\n"
	"    protected $isTest;\n"
	"\n"
	"    /**\n"
	"     * @var array 上传文件信息\n"
	"     */\n"
	"    protected $info;\n"
	"\n"
	"    /**\n"
	"     * @var array 文件 hash 信息\n"
	"     */\n"
	"    protected $hash = [];\n"
	"\n"
	"    /**\n"
	"     * File constructor.\n"
	"     * @access public\n"
	"     * @param  string $filename 文件名称\n"
	"     * @param  string $mode     访问模式\n"
	"     */\n"
	"    public function __construct($filename, $mode = \'r\')\n"
	"    {\n"
	"        parent::__construct($filename, $mode);\n"
	"        $this->filename = $this->getRealPath() ?: $this->getPathname();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置是否是单元测试\n"
	"     * @access public\n"
	"     * @param  bool $test 是否是测试\n"
	"     * @return $this\n"
	"     */\n"
	"    public function isTest($test = false)\n"
	"    {\n"
	"        $this->isTest = $test;\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置上传信息\n"
	"     * @access public\n"
	"     * @param  array $info 上传文件信息\n"
	"     * @return $this\n"
	"     */\n"
	"    public function setUploadInfo($info)\n"
	"    {\n"
	"        $this->info = $info;\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取上传文件的信息\n"
	"     * @access public\n"
	"     * @param  string $name 信息名称\n"
	"     * @return array|string\n"
	"     */\n"
	"    public function getInfo($name = \'\')\n"
	"    {\n"
	"        return isset($this->info[$name]) ? $this->info[$name] : $this->info;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取上传文件的文件名\n"
	"     * @access public\n"
	"     * @return string\n"
	"     */\n"
	"    public function getSaveName()\n"
	"    {\n"
	"        return $this->saveName;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置上传文件的保存文件名\n"
	"     * @access public\n"
	"     * @param  string $saveName 保存名称\n"
	"     * @return $this\n"
	"     */\n"
	"    public function setSaveName($saveName)\n"
	"    {\n"
	"        $this->saveName = $saveName;\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取文件的哈希散列值\n"
	"     * @access public\n"
	"     * @param  string $type 类型\n"
	"     * @return string\n"
	"     */\n"
	"    public function hash($type = \'sha1\')\n"
	"    {\n"
	"        if (!isset($this->hash[$type])) {\n"
	"            $this->hash[$type] = hash_file($type, $this->filename);\n"
	"        }\n"
	"\n"
	"        return $this->hash[$type];\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检查目录是否可写\n"
	"     * @access protected\n"
	"     * @param  string $path 目录\n"
	"     * @return boolean\n"
	"     */\n"
	"    protected function checkPath($path)\n"
	"    {\n"
	"        if (is_dir($path) || mkdir($path, 0755, true)) {\n"
	"            return true;\n"
	"        }\n"
	"\n"
	"        $this->error = [\'directory {:path} creation failed\', [\'path\' => $path]];\n"
	"\n"
	"        return false;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取文件类型信息\n"
	"     * @access public\n"
	"     * @return string\n"
	"     */\n"
	"    public function getMime()\n"
	"    {\n"
	"        $finfo = finfo_open(FILEINFO_MIME_TYPE);\n"
	"\n"
	"        return finfo_file($finfo, $this->filename);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置文件的命名规则\n"
	"     * @access public\n"
	"     * @param  string $rule 文件命名规则\n"
	"     * @return $this\n"
	"     */\n"
	"    public function rule($rule)\n"
	"    {\n"
	"        $this->rule = $rule;\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置上传文件的验证规则\n"
	"     * @access public\n"
	"     * @param  array $rule 验证规则\n"
	"     * @return $this\n"
	"     */\n"
	"    public function validate(array $rule = [])\n"
	"    {\n"
	"        $this->validate = $rule;\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检测是否合法的上传文件\n"
	"     * @access public\n"
	"     * @return bool\n"
	"     */\n"
	"    public function isValid()\n"
	"    {\n"
	"        return $this->isTest ? is_file($this->filename) : is_uploaded_file($this->filename);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检测上传文件\n"
	"     * @access public\n"
	"     * @param  array $rule 验证规则\n"
	"     * @return bool\n"
	"     */\n"
	"    public function check($rule = [])\n"
	"    {\n"
	"        $rule = $rule ?: $this->validate;\n"
	"\n"
	"        /* 检查文件大小 */\n"
	"        if (isset($rule[\'size\']) && !$this->checkSize($rule[\'size\'])) {\n"
	"            $this->error = \'filesize not match\';\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        /* 检查文件 Mime 类型 */\n"
	"        if (isset($rule[\'type\']) && !$this->checkMime($rule[\'type\'])) {\n"
	"            $this->error = \'mimetype to upload is not allowed\';\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        /* 检查文件后缀 */\n"
	"        if (isset($rule[\'ext\']) && !$this->checkExt($rule[\'ext\'])) {\n"
	"            $this->error = \'extensions to upload is not allowed\';\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        /* 检查图像文件 */\n"
	"        if (!$this->checkImg()) {\n"
	"            $this->error = \'illegal image files\';\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        return true;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检测上传文件后缀\n"
	"     * @access public\n"
	"     * @param  array|string $ext 允许后缀\n"
	"     * @return bool\n"
	"     */\n"
	"    public function checkExt($ext)\n"
	"    {\n"
	"        if (is_string($ext)) {\n"
	"            $ext = explode(\',\', $ext);\n"
	"        }\n"
	"\n"
	"        $extension = strtolower(pathinfo($this->getInfo(\'name\'), PATHINFO_EXTENSION));\n"
	"\n"
	"        return in_array($extension, $ext);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检测图像文件\n"
	"     * @access public\n"
	"     * @return bool\n"
	"     */\n"
	"    public function checkImg()\n"
	"    {\n"
	"        $extension = strtolower(pathinfo($this->getInfo(\'name\'), PATHINFO_EXTENSION));\n"
	"\n"
	"        // 如果上传的不是图片，或者是图片而且后缀确实符合图片类型则返回 true\n"
	"        return !in_array($extension, [\'gif\', \'jpg\', \'jpeg\', \'bmp\', \'png\', \'swf\']) || in_array($this->getImageType($this->filename), [1, 2, 3, 4, 6, 13]);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 判断图像类型\n"
	"     * @access protected\n"
	"     * @param  string $image 图片名称\n"
	"     * @return bool|int\n"
	"     */\n"
	"    protected function getImageType($image)\n"
	"    {\n"
	"        if (function_exists(\'exif_imagetype\')) {\n"
	"            return exif_imagetype($image);\n"
	"        }\n"
	"\n"
	"        try {\n"
	"            $info = getimagesize($image);\n"
	"            return $info ? $info[2] : false;\n"
	"        } catch (\\Exception $e) {\n"
	"            return false;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检测上传文件大小\n"
	"     * @access public\n"
	"     * @param  integer $size 最大大小\n"
	"     * @return bool\n"
	"     */\n"
	"    public function checkSize($size)\n"
	"    {\n"
	"        return $this->getSize() <= $size;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检测上传文件类型\n"
	"     * @access public\n"
	"     * @param  array|string $mime 允许类型\n"
	"     * @return bool\n"
	"     */\n"
	"    public function checkMime($mime)\n"
	"    {\n"
	"        $mime = is_string($mime) ? explode(\',\', $mime) : $mime;\n"
	"\n"
	"        return in_array(strtolower($this->getMime()), $mime);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 移动文件\n"
	"     * @access public\n"
	"     * @param  string      $path     保存路径\n"
	"     * @param  string|bool $savename 保存的文件名 默认自动生成\n"
	"     * @param  boolean     $replace  同名文件是否覆盖\n"
	"     * @return false|File\n"
	"     */\n"
	"    public function move($path, $savename = true, $replace = true)\n"
	"    {\n"
	"        // 文件上传失败，捕获错误代码\n"
	"        if (!empty($this->info[\'error\'])) {\n"
	"            $this->error($this->info[\'error\']);\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        // 检测合法性\n"
	"        if (!$this->isValid()) {\n"
	"            $this->error = \'upload illegal files\';\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        // 验证上传\n"
	"        if (!$this->check()) {\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        $path = rtrim($path, DS) . DS;\n"
	"        // 文件保存命名规则\n"
	"        $saveName = $this->buildSaveName($savename);\n"
	"        $filename = $path . $saveName;\n"
	"\n"
	"        // 检测目录\n"
	"        if (false === $this->checkPath(dirname($filename))) {\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        // 不覆盖同名文件\n"
	"        if (!$replace && is_file($filename)) {\n"
	"            $this->error = [\'has the same filename: {:filename}\', [\'filename\' => $filename]];\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        /* 移动文件 */\n"
	"        if ($this->isTest) {\n"
	"            rename($this->filename, $filename);\n"
	"        } elseif (!move_uploaded_file($this->filename, $filename)) {\n"
	"            $this->error = \'upload write error\';\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        // 返回 File 对象实例\n"
	"        $file = new self($filename);\n"
	"        $file->setSaveName($saveName)->setUploadInfo($this->info);\n"
	"\n"
	"        return $file;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取保存文件名\n"
	"     * @access protected\n"
	"     * @param  string|bool $savename 保存的文件名 默认自动生成\n"
	"     * @return string\n"
	"     */\n"
	"    protected function buildSaveName($savename)\n"
	"    {\n"
	"        // 自动生成文件名\n"
	"        if (true === $savename) {\n"
	"            if ($this->rule instanceof \\Closure) {\n"
	"                $savename = call_user_func_array($this->rule, [$this]);\n"
	"            } else {\n"
	"                switch ($this->rule) {\n"
	"                    case \'date\':\n"
	"                        $savename = date(\'Ymd\') . DS . md5(microtime(true));\n"
	"                        break;\n"
	"                    default:\n"
	"                        if (in_array($this->rule, hash_algos())) {\n"
	"                            $hash     = $this->hash($this->rule);\n"
	"                            $savename = substr($hash, 0, 2) . DS . substr($hash, 2);\n"
	"                        } elseif (is_callable($this->rule)) {\n"
	"                            $savename = call_user_func($this->rule);\n"
	"                        } else {\n"
	"                            $savename = date(\'Ymd\') . DS . md5(microtime(true));\n"
	"                        }\n"
	"                }\n"
	"            }\n"
	"        } elseif (\'\' === $savename || false === $savename) {\n"
	"            $savename = $this->getInfo(\'name\');\n"
	"        }\n"
	"\n"
	"        if (!strpos($savename, \'.\')) {\n"
	"            $savename .= \'.\' . pathinfo($this->getInfo(\'name\'), PATHINFO_EXTENSION);\n"
	"        }\n"
	"\n"
	"        return $savename;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取错误代码信息\n"
	"     * @access private\n"
	"     * @param  int $errorNo 错误号\n"
	"     * @return $this\n"
	"     */\n"
	"    private function error($errorNo)\n"
	"    {\n"
	"        switch ($errorNo) {\n"
	"            case 1:\n"
	"            case 2:\n"
	"                $this->error = \'upload File size exceeds the maximum value\';\n"
	"                break;\n"
	"            case 3:\n"
	"                $this->error = \'only the portion of file is uploaded\';\n"
	"                break;\n"
	"            case 4:\n"
	"                $this->error = \'no file to uploaded\';\n"
	"                break;\n"
	"            case 6:\n"
	"                $this->error = \'upload temp dir not found\';\n"
	"                break;\n"
	"            case 7:\n"
	"                $this->error = \'file write error\';\n"
	"                break;\n"
	"            default:\n"
	"                $this->error = \'unknown upload error\';\n"
	"        }\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取错误信息（支持多语言）\n"
	"     * @access public\n"
	"     * @return string\n"
	"     */\n"
	"    public function getError()\n"
	"    {\n"
	"        if (is_array($this->error)) {\n"
	"            list($msg, $vars) = $this->error;\n"
	"        } else {\n"
	"            $msg  = $this->error;\n"
	"            $vars = [];\n"
	"        }\n"
	"\n"
	"        return Lang::has($msg) ? Lang::get($msg, $vars) : $msg;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 魔法方法，获取文件的 hash 值\n"
	"     * @access public function __call($method, $args)\n"
	"     * @param  string $method 方法名\n"
	"     * @param  mixed  $args   调用参数\n"
	"     * @return string\n"
	"     */\n"
	"    public function __call($method, $args)\n"
	"    {\n"
	"        return $this->hash($method);\n"
	"    }\n"
	"}\n"
	"\n"
;
#endif